
	/***********************************************************************************************

		@API
		Factory: jsl.Object

		Static only:
			obj		create			(prototype*)

		Api
			obj		Object			(v)
			ks		keys				()
			obj		oid					(oid*)
			obj		sid					(sid*)

			obj		augment			(obj)
			obj   clone				(depth*)

			obj		walk				(action, obj*)
			it		iterator		()

			obj		map					(rule, obj*)
			obj		filter			(rule, obj*)
			b			some				(rule, obj*)
			b			every				(rule, obj*)
			v			reduce			(rule, value*)

			b			empty				()
			idx		isIn				(values..)
			b			instanceOf	(types..)

		Legend:
			action, rule:	fn(id, v, obj)

	************************************************************************************************/

  //-------------------------------------------------------------------------------
  jsl.Object = function(v) {
  	try {
  		var id, prt, obj//!
	    if(arguments.length > 1)	throw jsl.ParamError()//!

	    if(arguments.length) {//!
				if(v == null) throw jsl.ParamError("NullValue:v")//!

	    			 if(v.__augmented)					return v
				else if(v instanceof Error) 		return jsl.Error(v)
			 	else if(v instanceof Array)  		{ if(!jsl.__libs["lang"]) jsl.require("lang"); return jsl.Array(v) 		}
		    else if(v instanceof Boolean)		{ if(!jsl.__libs["lang"]) jsl.require("lang"); return jsl.Boolean(v) 	}
		    else if(v instanceof Date)  		{ if(!jsl.__libs["lang"]) jsl.require("lang"); return jsl.Date(v) 		}
		    else if(v instanceof Function)	{ if(!jsl.__libs["lang"]) jsl.require("lang"); return jsl.Function(v) }
		    else if(v instanceof Number)		{ if(!jsl.__libs["lang"]) jsl.require("lang"); return jsl.Number(v) 	}
		    else if(v instanceof String)  	{ if(!jsl.__libs["lang"]) jsl.require("lang"); return jsl.String(v) 	}
				else obj = v
			}
			else
				obj = {}

			prt = jsl.Object.prototype
    	for(id in prt) obj[id] = prt[id]
			return obj
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
  }
  //-------------------------------------------------------------------------------
	jsl.Object.__name									= "jsl.Object"
	jsl.Object.__augmented						= true
  jsl.Object.__native								= { create: true }
  //-------------------------------------------------------------------------------
	jsl.Object.prototype.__name 			= "jsl.Object"
	jsl.Object.prototype.__augmented 	= true
	jsl.Object.prototype.__native 		= {}
	jsl.Object.prototype.__oid 				= null
	jsl.Object.prototype.__sid 				= null
	jsl.Object.prototype.__cls 				= null
	//-------------------------------------------------------------------------------
	jsl.Object.create = function(prototype) {
		try {//!
			if(arguments.length > 1)	throw jsl.ParamError()
			if(arguments.length)			jsl.validate(prototype, "o", "prototype")//!

			if(arguments.length) {
				jsl.__f.prototype = prototype
				return new jsl.__f
			}
			else
				return {}
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Object.prototype.keys = function() {
		try {
			var ks, obj//!
			if(arguments.length)	throw jsl.ParamError()//!

			ks 	= []
			obj	= this

			jsl.Object.prototype.walk.call(obj, function(v, id) {
				if(!obj.hasOwnProperty || obj.hasOwnProperty(id))
					ks.push(id)
			})

			return ks
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.Object.prototype.oid = function(oid) {
    try {
    	var b, v//!
      if(arguments.length > 1)	throw jsl.ParamError()

      if(arguments.length && oid != null) {
				jsl.validate(oid, "s+", "oid")
				b = jsl.__objs[oid]
				if(b && jsl.__objs[oid] !== this)	throw jsl.ParamError("AlreadyDefined:oid")
			}//!

      if(arguments.length) {
	      if(oid != this.__oid) {

					if(this.__oid)	delete jsl.__objs[this.__oid]
		      if(oid) 				jsl.__objs[oid] = this

		      this.__oid = oid ? oid + "" : null
	      }
	      v = this
      }
      else
      	v = this.__oid || null

    	return v
    }
    catch(e) {
      jsl.throwError(e, this, arguments)
    }
  }
  //-------------------------------------------------------------------------------
  jsl.Object.prototype.sid = function(sid) {
    try {
    	var v//!
      if(arguments.length > 1)  					throw jsl.ParamError()
			if(arguments.length && sid != null)	jsl.validate(sid, "qid", "sid")//!

			if(arguments.length) {
				if(sid != null)	this.__sid = sid + ""
				else						this.__sid = null

	      v = this
			}
			else
      	v = this.__sid || null

      return v
    }
    catch(e) {
      jsl.throwError(e, this, arguments)
    }
  }
  //-------------------------------------------------------------------------------
	jsl.Object.prototype.augment = function(obj) {
		try {//!
			if(arguments.length !== 1)	throw	jsl.ParamError()
			jsl.validate(obj, "o", "obj")//!

			for(var id in obj)
				if(!obj.hasOwnProperty || obj.hasOwnProperty(id))
						this[id] = obj[id]

			return this
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Object.prototype.clone = function(depth) {
		try {
			var c, obj, objs, d, id, v, b, l//!
			if(arguments.length > 1)	throw	jsl.ParamError()
			if(arguments.length)			jsl.validate(depth, "t(b,i+)", "depth")//!

			c = this.constructor

						if(c === Array) 					obj = this.slice()
			else 	if(c === Boolean)					obj	= new Boolean(this.valueOf())
			else 	if(c === Date)						obj	= new Date(+this)
			else 	if(c === Error)						obj	= new Error(this.message)
			else 	if(c === TypeError)				obj	= new TypeError(this.message)
			else 	if(c === SyntaxError)			obj	= new SyntaxError(this.message)
			else 	if(c === EvalError)				obj	= new EvalError(this.message)
			else 	if(c === RangeError)			obj	= new RangeError(this.message)
			else 	if(c === ReferenceError)	obj	= new ReferenceError(this.message)
			else 	if(c === URIError)				obj	= new URIError(this.message)
			else 	if(c === Number)					obj	= new Number(+this)
			else	if(c === RegExp) 					obj = new RegExp(this)
			else 	if(c === String) 					obj = this.slice()
			else
				if(c === Function)
					try 			{ obj = jsl.__eval("obj = " + this) 			}
					catch(e)	{ throw jsl.ParamError("NativeFunction")	}

				else {
					//!the constructor property can be set to any value
					if(typeof c !== "function") throw jsl.MisuseError("BadType:constructor:function")//!

					//avoid arguments errors
					jsl.__f.prototype = c.prototype
					obj = new jsl.__f
				}

			if(depth) {

				if(typeof depth === "boolean") 	d = depth
				else if(depth > 0)							d = depth - 1
				else d = 0

				if(!arguments.callee.__i) {
					arguments.callee.__i		= 0
					arguments.callee.__objs = [ this ]
					arguments.callee.__objs["_0"] = obj
				}

				objs = arguments.callee.__objs
				arguments.callee.__i++

				for(id in this)
					if(!this.hasOwnProperty || this.hasOwnProperty(id))

						if(this[id] == null || typeof this[id] !== "object")
							obj[id] = this[id]

						else {

							v = this[id]
							for(b = 0, l = objs.length; b < l; b++)
								if(objs[b] === v)
									break;

							//1-object not found
							if(b === l) {
								objs[l] = v
								objs["*" + b]	= v = [[], []]

								obj[id] = arguments.callee.call(this[id], d)
								objs["_" + b]	= obj[id]

								for(b = 0, l = v[0].length; b < l; b++)
									v[1][b][v[0][b]] = obj[id]

								objs["*" + b] = null
							}

							//2-object found and already cloned
							else if(objs["_" + b])
								obj[id] = objs["_" + b]

							//3-object found but in cloning
							else {
								objs["*" + b][0].push(id)
								objs["*" + b][1].push(obj)
							}
						}

				arguments.callee.__i--
				if(!arguments.callee.__i)
					arguments.callee.__objs = null
			}
			else
				for(id in this)
					if(!this.hasOwnProperty || this.hasOwnProperty(id))
						obj[id] = this[id]

			return obj
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Object.prototype.walk = function(action, obj) {
		try {
			var id, v, ntv//!
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(action, "f", "action")
			if(arguments.length === 2)	jsl.validate(obj, "o", "obj")//!

			ntv = this.__native

			try {
				for(id in this)
					if(!ntv || !(id in ntv))
						if((v = obj ? action.call(obj, this[id], id, this)
												: action(this[id], id, this)) !== undefined)
							break

			}
			catch(e) {
				throw jsl.ParamError("BadScript:action", e)
			}

			return v || this
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
  jsl.Object.prototype.iterator = function() {
    try {
    	var it, obj, i//!
      if(arguments.length)	throw jsl.ParamError()//!

			it	= { __name: "Iterator", __ix: 0, __data: [] }
    	obj	= this
			i		= 0

			jsl.Object.prototype.walk.call(this, function(v, id) {
				if(!obj.__native || !(id in obj.__native))
					it.__data[i++] = id
			})

  		//-------------------------------------------------------------------------------
			it.hasNext = function() {
				try {//!
					if(arguments.length)	throw jsl.ParamError()//!

					while(this.__ix < this.__data.length && !(this.__data[this.__ix] in obj))
						this.__ix++

					return this.__ix < this.__data.length
				}
				catch(e) {
					jsl.throwError(e, this, arguments)
				}
			}
  		//-------------------------------------------------------------------------------
			it.next = function() {
				try {//!
					if(arguments.length) 	throw jsl.ParamError()
					if(!this.hasNext())		throw jsl.EndOfIterationError()//!

					return this.__data[this.__ix++]
				}
				catch(e) {
					jsl.throwError(e, this, arguments)
				}
			}

      return it
    }
    catch(e) {
      jsl.throwError(e, this, arguments)
    }
  }
	//-------------------------------------------------------------------------------
	jsl.Object.prototype.map = function(rule, obj) {
		try {
			var obj2//!
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(rule, "f", "rule")
			if(arguments.length === 2)	jsl.validate(obj, "o", "obj")//!

			obj2 = {}
			jsl.Object.prototype.walk.call(this, function(v, id, obj) {
				obj2[id] = rule.apply(this, arguments)
			}, obj || jsl.__go)

			return obj2
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Object.prototype.filter = function(rule, obj) {
		try {
			var obj2//!
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(rule, "f", "rule")
			if(arguments.length === 2)	jsl.validate(obj, "o", "obj")//!

			obj2 = {}
			jsl.Object.prototype.walk.call(this, function(v, id, obj) {
				if(rule.apply(this, arguments)) obj2[id] = v
			}, obj || jsl.__go)

			return obj2
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Object.prototype.some = function(rule, obj) {
		try {
			var b//!
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(rule, "f", "rule")
			if(arguments.length === 2)	jsl.validate(obj, "o", "obj")//!

			b = false
			jsl.Object.prototype.walk.call(this, function(v, id, obj) {
				if(rule.apply(this, arguments)) return (b = true)
			}, obj || jsl.__go)

			return b
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Object.prototype.every = function(rule, obj) {
		try {
			var b//!
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(rule, "f", "rule")
			if(arguments.length === 2)	jsl.validate(obj, "o", "obj")//!

			b = true
			jsl.Object.prototype.walk.call(this, function(v, id, obj) {
				if(!rule.apply(this, arguments)) { b = false; return true }
			}, obj || jsl.__go)

			return b
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Object.prototype.reduce = function(rule,  value) {
		try {
			var acc, i//!
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(rule, "f", "rule")//!

			i		= 0
			acc = value

			jsl.Object.prototype.walk.call(this, function(v, id, obj) {
				acc = rule(acc, v, id, obj)
				i++
			})

			//!
			if(!i && arguments.length === 1)	throw jsl.MisuseError()//!
			return acc
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Object.prototype.empty = function() {
		try {
			var ntv, b//!
			if(arguments.length)	throw jsl.ParamError()//!

			ntv = this.__native
			for(var id in this)
				if(!ntv || !(id in ntv)) {
					b = true
					break
				}

			return !b
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Object.prototype.isIn = function() {
		try {
			var args, len, v, arg, len2, a, b
			//!
			if(!arguments.length)	throw jsl.ParamError()//!

			args 	= arguments
			len		= args.length
			v			= false

			for(a = 0; a < len && !v; a++)
				if(args[a] instanceof Array) {

					arg 	= args[a]
					len2	= arg.length

					for(b = 0; b < len2 && !v; b++)
						if(this == arg[b])
							v = true
				}
				else if(this == args[a])
					v = true

			return v
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Object.prototype.instanceOf = function() {
		try {
			var fs, len, v, a
			//!
			if(!arguments.length)	throw jsl.ParamError()//!

			fs	= arguments
			len	= arguments.length
			v		= false

			for(a = 0; a < len && !v; a++) {//!
				jsl.validate(fs[a], "f", "types[" + a + "]")//!
				v = this instanceof fs[a]
			}

			return v
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}

	//Object init
	//-------------------------------------------------------------------------------
	;(function() {
		var id, Obj, prt

		Obj = jsl.Object
		prt = Obj.prototype

		for(id in prt) {

			Obj.__native[id] = true
			prt.__native[id] = true

			if(typeof prt[id] === "function") {

				Obj[id] = function(obj) {
					try {//!
						//is tollerate also a primitive value that is converted in the apply function into object
						if(!arguments.length)	throw jsl.ParamError()
						if(obj == null)				throw jsl.ParamError("NullValue:obj")//!

						return arguments.callee.__f.apply(obj, Array.prototype.slice.call(arguments, 1))
					}
					catch(e) {
						jsl.throwError(e, this, arguments)
					}
				}

				Obj[id].__name	= prt[id].__name	= id
				Obj[id].__f			= prt[id]
			}
		}
	})()
